package com.cin.cma.server.biz.job;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cin.cma.common.model.ApiResponse;
import com.cin.cma.common.model.finixx.response.*;
import com.cin.cma.server.biz.dal.domain.T0100PlaceinfoDO;
import com.cin.cma.server.biz.dal.domain.T0201FeatureAppDO;
import com.cin.cma.server.biz.dal.domain.TkSeatDO;
import com.cin.cma.server.biz.dal.service.IT0201FeatureAppService;
import com.cin.cma.server.biz.dal.service.ITkSeatService;
import com.cin.cma.server.biz.model.core.request.ScheduleRequestCO;
import com.cin.cma.server.biz.model.core.request.SeatPlanRequestCO;
import com.cin.cma.server.biz.controller.CoreController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：wubo
 * @Date：2025/3/11 下午7:10
 */
@Service
@Slf4j
public class SyncService {

    @Autowired
    private CoreController coreController;
    @Autowired
    private IT0201FeatureAppService t0201FeatureAppService;
    @Autowired
    private ITkSeatService tkSeatService;

    /**
     * 同步排期
     */
    public void syncSession(T0100PlaceinfoDO t0100PlaceinfoDO, Date date) {
        ScheduleRequestCO scheduleRequestCO = new ScheduleRequestCO();
        scheduleRequestCO.setCinemaLinkId(t0100PlaceinfoDO.getCinemalinkid());
        scheduleRequestCO.setStartDate(date);
        ApiResponse<SessionResponse> apiResponse = coreController.ticketGetSessions(scheduleRequestCO);
        if (apiResponse.getSuccess()) {
            SessionResponse sessionResponse = apiResponse.getData();
            List<T0201FeatureAppDO> waitDbList = new ArrayList<>();

            List<Map<String, Object>> hallCodeSeatCountObjectMap = tkSeatService.listMaps(new QueryWrapper<TkSeatDO>()
                    .select("HALL_CODE", "count(*) as COUNT")
                    .eq("CINEMA_CODE", t0100PlaceinfoDO.getPlaceno())
                    .groupBy("HALL_CODE")
            );
            Map<String, Integer> hallCodeSeatCountMap = new HashMap<>();
            for (Map<String, Object> map : hallCodeSeatCountObjectMap) {
                hallCodeSeatCountMap.put((String) map.get("HALL_CODE"), ((BigDecimal) map.get("COUNT")).intValue());
            }

            for (SessionsItemResponse session : sessionResponse.getSessions()) {
                T0201FeatureAppDO t0201FeatureAppDO = new T0201FeatureAppDO();
                t0201FeatureAppDO.setFeatureno(session.getRefSeqNo());
                t0201FeatureAppDO.setFeaturekey(session.getFilmCd());
                t0201FeatureAppDO.setPlaceno(t0100PlaceinfoDO.getPlaceno());
                t0201FeatureAppDO.setAppcode("");
                t0201FeatureAppDO.setStandpric(session.getMarketPrice());
                t0201FeatureAppDO.setApppric(BigDecimal.ZERO);
                t0201FeatureAppDO.setBalancepric(session.getLeastPrice());
                t0201FeatureAppDO.setPlacename(t0100PlaceinfoDO.getPlacename());
                t0201FeatureAppDO.setHallno(session.getCinemaCd());
                t0201FeatureAppDO.setHallname(session.getCinemaName());
                t0201FeatureAppDO.setFilmno(session.getFilmCode());
                t0201FeatureAppDO.setFilmname(session.getFilmLongTitle());
                t0201FeatureAppDO.setCorrelated("");
                Date showTime = DateUtil.parse(session.getShowDate() + session.getShowTimeInt(), "yyyy-MM-ddHHmm");

                t0201FeatureAppDO.setFeaturedate(session.getShowDate());
                t0201FeatureAppDO.setFeaturetime(DateUtil.format(showTime, "HH:mm"));
                t0201FeatureAppDO.setTotaltime(DateUtil.format(DateUtil.offsetMinute(showTime, session.getFilmDuration()), "HH:mm"));
                //todo 填几？
                t0201FeatureAppDO.setSetclose("1");
                t0201FeatureAppDO.setFilmname1("");
                t0201FeatureAppDO.setSefeatureno("");
                t0201FeatureAppDO.setAdddatetime(new Date());
                t0201FeatureAppDO.setUsesign("0");
                t0201FeatureAppDO.setCopylanguage(session.getLanguageName());
                t0201FeatureAppDO.setAndroidpric(BigDecimal.ZERO);
                t0201FeatureAppDO.setTotalseats(hallCodeSeatCountMap.getOrDefault(t0201FeatureAppDO.getHallno(), 0));
                t0201FeatureAppDO.setRemainingseats(0);
                t0201FeatureAppDO.setWinxinpric(session.getLeastPrice());
                t0201FeatureAppDO.setUpdatetime(null);
                t0201FeatureAppDO.setFlag("");
                t0201FeatureAppDO.setHallseats("");
                t0201FeatureAppDO.setCopytype(session.getFilmCarryName());
                t0201FeatureAppDO.setWebsitepric(session.getMarketPrice());
                t0201FeatureAppDO.setStatus("1");
                t0201FeatureAppDO.setOriginalapprice(BigDecimal.ZERO);
                t0201FeatureAppDO.setSelfprice(session.getLeastPrice());
                t0201FeatureAppDO.setPricestr("黑卡:5折");
                t0201FeatureAppDO.setFee(BigDecimal.ZERO);
                waitDbList.add(t0201FeatureAppDO);
            }
            if (CollUtil.isNotEmpty(waitDbList)) {
                List<T0201FeatureAppDO> existDbList = t0201FeatureAppService.list(new LambdaQueryWrapper<T0201FeatureAppDO>()
                        .eq(T0201FeatureAppDO::getPlaceno, t0100PlaceinfoDO.getPlaceno())
                        .eq(T0201FeatureAppDO::getFeaturedate, DateUtil.formatDate(date)));
                Map<String, T0201FeatureAppDO> existFeaturenoDataMap = existDbList.stream().collect(Collectors.toMap(T0201FeatureAppDO::getFeatureno, v -> v));
                Map<String, T0201FeatureAppDO> waitDbFeaturenoDataMap = waitDbList.stream().collect(Collectors.toMap(T0201FeatureAppDO::getFeatureno, v -> v));
                //等待新增的列表:waitDbList中有，existDbList中没有
                List<T0201FeatureAppDO> waitInsertList = new ArrayList<>();
                //等待更新的列表:waitDbList中有，existDbList中也有
                List<T0201FeatureAppDO> waitUpdateList = new ArrayList<>();
                //等待删除的列表:waitDbList中没有，existDbList中有
                List<T0201FeatureAppDO> waitDeleteList = new ArrayList<>();

                for (T0201FeatureAppDO t0201FeatureAppDO : waitDbList) {
                    T0201FeatureAppDO existDb = existFeaturenoDataMap.get(t0201FeatureAppDO.getFeatureno());
                    if (existDb != null) {
                        t0201FeatureAppDO.setFeatureappno(existDb.getFeatureappno());
                        t0201FeatureAppDO.setAdddatetime(new Date());
                        waitUpdateList.add(t0201FeatureAppDO);
                    } else {
                        t0201FeatureAppDO.setAdddatetime(new Date());
                        waitInsertList.add(t0201FeatureAppDO);
                    }
                }
                for (T0201FeatureAppDO t0201FeatureAppDO : existDbList) {
                    if (!waitDbFeaturenoDataMap.containsKey(t0201FeatureAppDO.getFeatureno())) {
                        t0201FeatureAppDO.setAdddatetime(new Date());
                        //todo 什么状态表示排期无效？
                        t0201FeatureAppDO.setStatus("0");
                        t0201FeatureAppDO.setSetclose("1");
                        waitDeleteList.add(t0201FeatureAppDO);
                    }
                }
                if (CollUtil.isNotEmpty(waitInsertList)) {
                    t0201FeatureAppService.saveBatch(waitInsertList);
                }
                if (CollUtil.isNotEmpty(waitUpdateList)) {
                    t0201FeatureAppService.updateBatchById(waitUpdateList);
                }
                if (CollUtil.isNotEmpty(waitDeleteList)) {
                    t0201FeatureAppService.updateBatchById(waitUpdateList);
                }
                log.info("同步排期完成，影院编码：{}，日期：{}，新增：{}，修改：{}，删除：{}", t0100PlaceinfoDO.getPlaceno(), DateUtil.formatDate(date), waitInsertList.size(), waitUpdateList.size(), waitDeleteList.size());
            }
        }
    }

    /**
     * 同步基础座位图
     *
     * @param t0100PlaceInfo
     */
    public void syncSeat(T0100PlaceinfoDO t0100PlaceInfo) {
        ApiResponse<HallsResponse> hallsResponseApiResponse = coreController.ticketGetHalls(t0100PlaceInfo.getCinemalinkid());
        if (hallsResponseApiResponse.getSuccess()) {
            HallsResponse hallsResponse = hallsResponseApiResponse.getData();
            List<TkSeatDO> waitDbList = new ArrayList<>();
            for (HallNodeResponse hallNodeResponse : hallsResponse.getHalls()) {
                SeatPlanRequestCO seatPlanRequestCO = new SeatPlanRequestCO();
                seatPlanRequestCO.setHallCode(hallNodeResponse.getCinemaCd());
                seatPlanRequestCO.setCinemaLinkId(t0100PlaceInfo.getCinemalinkid());
                ApiResponse<SeatPlanResponse> seatPlanResponseApiResponse = coreController.ticketGetSeatplan(seatPlanRequestCO);
                if (seatPlanResponseApiResponse.getSuccess()) {
                    SeatPlanResponse seatPlanResponse = seatPlanResponseApiResponse.getData();
                    for (SeatPlansItemResponse seatPlansItemResponse : seatPlanResponse.getSeatPlans()) {
                        List<TkSeatDO> oneHallSeatList = new ArrayList<>();
                        for (SeatsMsgItemResponse seatsMsgItemResponse : seatPlansItemResponse.getSeats()) {
                            TkSeatDO tkSeatDO = new TkSeatDO();
                            tkSeatDO.setCinemaCode(t0100PlaceInfo.getPlaceno());
                            tkSeatDO.setSectionCode(seatsMsgItemResponse.getSectionId());
                            tkSeatDO.setHallCode(seatPlansItemResponse.getCinemaCd());
                            tkSeatDO.setSeatCode(seatsMsgItemResponse.getSeatCode());
                            tkSeatDO.setRowId(seatsMsgItemResponse.getRowId());
                            tkSeatDO.setColumnId(seatsMsgItemResponse.getColId());
                            tkSeatDO.setSeatplanX(seatsMsgItemResponse.getColNum());
                            tkSeatDO.setSeatplanY(seatsMsgItemResponse.getRowNum());
                            tkSeatDO.setSeatName(StrUtil.format("{}排{}座", seatsMsgItemResponse.getRowNum(), seatsMsgItemResponse.getColNum()));
                            tkSeatDO.setDelFlag(0);
                            //B:包厢;H:保留;W:残疾座位;Z:按摩椅;N:普通座位;L:情侣座;R:情侣座
                            tkSeatDO.setSeatType(seatsMsgItemResponse.getSeatType());
                            tkSeatDO.setDamagedFlag(seatsMsgItemResponse.getSeatIsDamaged() ? 1 : 0);
                            tkSeatDO.setCreator("job");
                            tkSeatDO.setCreateTime(new Date());
                            oneHallSeatList.add(tkSeatDO);
                        }
                        //按照sectionCode、SeatplanX、SeatplanY升序排序
                        oneHallSeatList.sort(Comparator.comparing(TkSeatDO::getSectionCode).thenComparing(TkSeatDO::getSeatplanY).thenComparing(TkSeatDO::getSeatplanX));
                        for (int i = 0; i < oneHallSeatList.size(); i++) {
                            TkSeatDO tkSeatDO = oneHallSeatList.get(i);
                            //todo 情侣座处理，未测试
                            // 排序后，当前座位是情侣座L,那么下一个必然是情侣座R
                            if ("L".equals(tkSeatDO.getSeatType())) {
                                if (i + 1 < oneHallSeatList.size()) {
                                    TkSeatDO nextSeat = oneHallSeatList.get(i + 1);
                                    if ("R".equals(nextSeat.getSeatType())) {
                                        String loveCode = tkSeatDO.getRowId() + "_" + tkSeatDO.getColumnId() + "_" + nextSeat.getRowId() + "_" + nextSeat.getColumnId();
                                        tkSeatDO.setLoveCode(loveCode);
                                        nextSeat.setLoveCode(loveCode);
                                    }
                                }
                            }
                        }
                        waitDbList.addAll(oneHallSeatList);
                    }
                }
            }

            if (CollUtil.isNotEmpty(waitDbList)) {
                List<TkSeatDO> existDbList = tkSeatService.list(new LambdaQueryWrapper<TkSeatDO>()
                        .eq(TkSeatDO::getCinemaCode, t0100PlaceInfo.getPlaceno()));

                Map<String, TkSeatDO> existSeatDataMap = existDbList.stream().collect(Collectors.toMap(this::getSyncSeatUniqueKey, v -> v));
                Map<String, TkSeatDO> waitDbSeatDataMap = waitDbList.stream().collect(Collectors.toMap(this::getSyncSeatUniqueKey, v -> v));
                //等待新增的列表:waitDbList中有，existDbList中没有
                List<TkSeatDO> waitInsertList = new ArrayList<>();
                //等待更新的列表:waitDbList中有，existDbList中也有
                List<TkSeatDO> waitUpdateList = new ArrayList<>();
                //等待删除的列表:waitDbList中没有，existDbList中有
                List<TkSeatDO> waitDeleteList = new ArrayList<>();

                for (TkSeatDO tkSeatDO : waitDbList) {
                    String syncSeatUniqueKey = getSyncSeatUniqueKey(tkSeatDO);
                    TkSeatDO existDb = existSeatDataMap.get(syncSeatUniqueKey);
                    if (existDb != null) {
                        if (!tkSeatDO.equals(existDb)) {
                            tkSeatDO.setSeatid(existDb.getSeatid());
                            tkSeatDO.setModified(new Date());
                            waitUpdateList.add(tkSeatDO);
                        }
                    } else {
                        waitInsertList.add(tkSeatDO);
                    }
                }
                for (TkSeatDO tkSeatDO : existDbList) {
                    String syncSeatUniqueKey = getSyncSeatUniqueKey(tkSeatDO);
                    if (!waitDbSeatDataMap.containsKey(syncSeatUniqueKey)) {
                        tkSeatDO.setModified(new Date());
                        tkSeatDO.setDelFlag(1);
                        waitDeleteList.add(tkSeatDO);
                    }
                }
                if (CollUtil.isNotEmpty(waitInsertList)) {
                    tkSeatService.saveBatch(waitInsertList);
                }
                if (CollUtil.isNotEmpty(waitUpdateList)) {
                    tkSeatService.updateBatchById(waitUpdateList);
                }
                if (CollUtil.isNotEmpty(waitDeleteList)) {
                    tkSeatService.updateBatchById(waitUpdateList);
                }
                log.info("同步座位图完成，影院编码：{}，新增：{}，修改：{}，删除：{}", t0100PlaceInfo.getPlaceno(), waitInsertList.size(), waitUpdateList.size(), waitDeleteList.size());
            }
        }
    }

    private String getSyncSeatUniqueKey(TkSeatDO tkSeatDO) {
        return StrUtil.format("{}_{}_{}_{}", tkSeatDO.getCinemaCode(), tkSeatDO.getSectionCode(), tkSeatDO.getHallCode(), tkSeatDO.getSeatCode());
    }
}